#include "lexer.h"
#include "parser.h"
#include <stdio.h>

int test_1()
{

    char *input = "=+(){},;";
    struct s_lexer l = new_s_lexer(input);
    struct s_token tokens[9] = {new_s_token(ASSIGN, "="), new_s_token(PLUS, "+"),      new_s_token(LPAREN, "("),
                                new_s_token(RPAREN, ")"), new_s_token(LBRACE, "{"),    new_s_token(RBRACE, "}"),
                                new_s_token(COMMA, ","),  new_s_token(SEMICOLON, ";"), new_s_token(MEOF, "")};
    for (int i = 0; i < 9; i++)
    {
        struct s_token t = s_lexer_next_token(&l);
        if (s_token_eq(tokens[i], t) == 0)
        {
            char s1[1052], s2[1052];
            s_token_to_str(&tokens[i], s1);
            s_token_to_str(&t, s2);
            printf("num: %d, e: %s, a: %s\n", i, s1, s2);
            printf("test_1: failed\n");
            return 1;
        }
    }
    printf("test_1: passed\n");
    return 0;
}

int test_2()
{

    char *input = "let five = 5;\nlet ten = 10;\n\nlet add = fn(x,y) {x+y};\n "
                  "let result = add(five, ten);\n";
    struct s_lexer l = new_s_lexer(input);
    struct s_token tokens[36] = {new_s_token(LET, "let"),     new_s_token(IDENT, "five"),  new_s_token(ASSIGN, "="),
                                 new_s_token(INT, "5"),       new_s_token(SEMICOLON, ";"), new_s_token(LET, "let"),
                                 new_s_token(IDENT, "ten"),   new_s_token(ASSIGN, "="),    new_s_token(INT, "10"),
                                 new_s_token(SEMICOLON, ";"), new_s_token(LET, "let"),     new_s_token(IDENT, "add"),
                                 new_s_token(ASSIGN, "="),    new_s_token(FUNCTION, "fn"), new_s_token(LPAREN, "("),
                                 new_s_token(IDENT, "x"),     new_s_token(COMMA, ","),     new_s_token(IDENT, "y"),
                                 new_s_token(RPAREN, ")"),    new_s_token(LBRACE, "{"),    new_s_token(IDENT, "x"),
                                 new_s_token(PLUS, "+"),      new_s_token(IDENT, "y"),     new_s_token(RBRACE, "}"),
                                 new_s_token(SEMICOLON, ";"), new_s_token(LET, "let"),     new_s_token(IDENT, "result"),
                                 new_s_token(ASSIGN, "="),    new_s_token(IDENT, "add"),   new_s_token(LPAREN, "("),
                                 new_s_token(IDENT, "five"),  new_s_token(COMMA, ","),     new_s_token(IDENT, "ten"),
                                 new_s_token(RPAREN, ")"),    new_s_token(SEMICOLON, ";"), new_s_token(MEOF, "")};
    for (int i = 0; i < 36; i++)
    {
        struct s_token t = s_lexer_next_token(&l);
        if (s_token_eq(tokens[i], t) == 0)
        {
            char s1[1052], s2[1052];
            s_token_to_str(&tokens[i], s1);
            s_token_to_str(&t, s2);
            printf("num: %d, e: %s, a: %s\n", i, s1, s2);
            printf("test_2: failed\n");
            return 1;
        }
    }
    printf("test_2: passed\n");
    return 0;
}

int test_3()
{
    char *input = "!-/*5;\n5 < 10 > 5;\n";
    struct s_lexer l = new_s_lexer(input);
    struct s_token tokens[12] = {new_s_token(BANG, "!"),     new_s_token(MINUS, "-"), new_s_token(SLASH, "/"),
                                 new_s_token(ASTERISK, "*"), new_s_token(INT, "5"),   new_s_token(SEMICOLON, ";"),
                                 new_s_token(INT, "5"),      new_s_token(LT, "<"),    new_s_token(INT, "10"),
                                 new_s_token(GT, ">"),       new_s_token(INT, "5"),   new_s_token(SEMICOLON, ";")};
    for (int i = 0; i < 12; i++)
    {
        struct s_token t = s_lexer_next_token(&l);
        if (s_token_eq(tokens[i], t) == 0)
        {
            char s1[1052], s2[1052];
            s_token_to_str(&tokens[i], s1);
            s_token_to_str(&t, s2);
            printf("num: %d, e: %s, a: %s\n", i, s1, s2);
            printf("test_3: failed\n");
            return 1;
        }
    }
    printf("test_3: passed\n");
    return 0;
}

int test_4()
{
    char *input = "if (5 < 10) {\nreturn true;\n} else {\nreturn false;\n}\n";
    struct s_lexer l = new_s_lexer(input);
    struct s_token tokens[17] = {
        new_s_token(IF, "if"),       new_s_token(LPAREN, "("),      new_s_token(INT, "5"),
        new_s_token(LT, "<"),        new_s_token(INT, "10"),        new_s_token(RPAREN, ")"),
        new_s_token(LBRACE, "{"),    new_s_token(RETURN, "return"), new_s_token(TRUE, "true"),
        new_s_token(SEMICOLON, ";"), new_s_token(RBRACE, "}"),      new_s_token(ELSE, "else"),
        new_s_token(LBRACE, "{"),    new_s_token(RETURN, "return"), new_s_token(FALSE, "false"),
        new_s_token(SEMICOLON, ";"), new_s_token(RBRACE, "}")};
    for (int i = 0; i < 12; i++)
    {
        struct s_token t = s_lexer_next_token(&l);
        if (s_token_eq(tokens[i], t) == 0)
        {
            char s1[1052], s2[1052];
            s_token_to_str(&tokens[i], s1);
            s_token_to_str(&t, s2);
            printf("num: %d, e: %s, a: %s\n", i, s1, s2);
            printf("test_4: failed\n");
            return 1;
        }
    }
    printf("test_4: passed\n");
    return 0;
}

int test_5()
{
    char *input = "10 == 10;\n10 != 9;\n";
    struct s_lexer l = new_s_lexer(input);
    struct s_token tokens[8] = {new_s_token(INT, "10"),      new_s_token(EQ, "=="),      new_s_token(INT, "10"),
                                new_s_token(SEMICOLON, ";"), new_s_token(INT, "10"),     new_s_token(NOT_EQ, "!="),
                                new_s_token(INT, "9"),       new_s_token(SEMICOLON, ";")};
    for (int i = 0; i < 8; i++)
    {
        struct s_token t = s_lexer_next_token(&l);
        if (s_token_eq(tokens[i], t) == 0)
        {
            char s1[1052], s2[1052];
            s_token_to_str(&tokens[i], s1);
            s_token_to_str(&t, s2);
            printf("num: %d, e: %s, a: %s\n", i, s1, s2);
            printf("test_5: failed\n");
            return 1;
        }
    }
    printf("test_5: passed\n");
    return 0;
}


int test_let_statements(){

    char *input = "let x = 5;\nlet y = 10;\nlet foobar = 838383;\n";
    struct s_lexer l = new_s_lexer(input);
//    struct s_parser p = new_parser(&l);

//    struct s_program *program = s_parser_parse_program(&p);

    struct s_token tokens[16] = {new_s_token(LET, "let"), new_s_token(IDENT, "x"), new_s_token(ASSIGN, "="), new_s_token(INT, "5"), new_s_token(SEMICOLON, ";"),

                                new_s_token(LET, "let"), new_s_token(IDENT, "y"), new_s_token(ASSIGN, "="), new_s_token(INT, "10"), new_s_token(SEMICOLON, ";"),

                                new_s_token(LET, "let"), new_s_token(IDENT, "foobar"), new_s_token(ASSIGN, "="), new_s_token(INT, "838383"), new_s_token(SEMICOLON, ";"),

                                new_s_token(MEOF, "")};


    for (int i = 0; i < 16; i++)
    {
        struct s_token t = s_lexer_next_token(&l);
        if (s_token_eq(tokens[i], t) == 0)
        {
            char s1[1052], s2[1052];
            s_token_to_str(&tokens[i], s1);
            s_token_to_str(&t, s2);
            printf("num: %d, e: %s, a: %s\n", i, s1, s2);
            printf("test_let_statements: failed\n");
            return 1;
        }
    }

    printf("test_let_statements: passed\n");
    return 0;
}